當初會寫這篇參考筆記,主要是因為, Selenium-Python 的中文文件,看起來應該是大陸人翻譯的,只有簡體中文,沒有繁體中文的版本,所以我就自己整理了繁體中文的版本,再把裡面的大陸用語轉換成台灣用語(先說我不是專業的,用詞錯誤請不要噴我w),增加或刪減一些文字,以方便肉眼閱讀XD。
特此撰寫本篇文章作為紀錄文件,用以方便後續有需要的時候,可以快速的重複查閱,雖然後面比較沒有什麼機會再用到,但也算是一個還不錯的經驗。
指令如下:
pip3 install selenium
請前往下方連結,下載對應版本的 Chrome Driver,並將壓縮檔內的chromedriver.exe解壓縮到指定的工作目錄。
ChromeDriver - WebDriver for Chrome
開啟 Chrome 瀏覽器,並前往 Google 搜尋頁面,然後再關閉瀏覽器,程式碼如下:
from selenium import webdriver
driver = webdriver.Chrome('chromedriver.exe')
driver.get('https://www.google.com')
driver.close()
當你通過 class name 查找元素時可使用這個。在該策略下,頁面中第一個匹配該 class 屬性的元素會被匹配並返回。如果找不到任何元素,則會拋出 NoSuchElementException 異常。
driver.find_element_by_class_name('class name')
當你通過CSS選擇器查找元素時可以使用這個。在該策略下,頁面中第一個匹配該 CSS 選擇器的元素會被匹配並返回。如果找不到任何元素,則會拋出 NoSuchElementException 異常。
driver.find_element_by_css_selector('css selector')
當你知道一個元素的 id 時,你可以使用本方法。在該策略下,頁面中第一個符合該 id 的元素會被匹配並返回。如果找不到任何元素,會拋出 NoSuchElementException 異常。
driver.find_element_by_id('id')
當你知道在一個連結標籤中使用的文字時可使用這個。在該策略下,頁面中第一個匹配連結文字的標籤會被匹配並返回。如果找不到任何元素,則會拋出 NoSuchElementException 異常。
driver.find_element_by_link_text('link text')
也可以只用連結的部分文字定位元素:
driver.find_element_by_partial_link_text('partial link text')
當你知道一個元素的 name 時,你可以使用本方法。在該策略下,頁面中第一個該 name 元素會被匹配並返回。如果找不到任何元素,會拋出 NoSuchElementException 異常。
driver.find_element_by_name('name')
當你通過標籤名 tag 查找元素時可使用這個。在該策略下,頁面中第一個匹配該標籤名的元素 會被匹配並返回。如果找不到任何元素,會拋出 NoSuchElementException 異常。
driver.find_element_by_tag_name('tag')
XPath是XML文檔中查找結點的語法。因為HTML文檔也可以被轉換成XML(XHTML)文檔, Selenium的用戶可以利用這種強大的語言在web應用中查找元素。 XPath擴展了(當然也支持)這種通過id或name屬性獲取元素的簡單方式,同時也開闢了各種新的可能性, 例如獲取頁面上的第三個複選框。
使用XPath的主要原因之一就是當你想獲取一個既沒有id屬性也沒有name屬性的元素時, 你可以通過XPath使用元素的絕對位置來獲取他(這是不推薦的),或相對於有一個id或name屬性的元素(理論上的父元素)的來獲取你想要的元素。 XPath定位器也可以通過非id和name屬性查找元素。
絕對的XPath是所有元素都從根元素的位置(HTML)開始定位,只要應用中有輕微的調整,會就導致你的定位失敗。但是通過就近的包含id或者name屬性的元素出發定位你的元素,這樣相對關係就很靠譜, 因為這種位置關係很少改變,所以可以使你的測試更加強大。
driver.find_element_by_xpath('//*[@id="lst-ib"]')
開啟 Chrome 瀏覽器,並前往 Google 搜尋頁面,然後搜尋"你好"並按下 Enter,程式碼如下:
from selenium import webdriver
driver = webdriver.Chrome('chromedriver.exe')
driver.get('https://www.google.com')
q = driver.find_element_by_name('q')
q.send_keys('你好')
from selenium.webdriver.common.keys import Keys
q.send_keys(Keys.RETURN)
開啟 Chrome 瀏覽器,並前往 Google 搜尋頁面,然後點擊登入按鈕,程式碼如下:
from selenium import webdriver
driver = webdriver.Chrome('chromedriver.exe')
driver.get('https://www.google.com')
login = driver.find_element_by_link_text('登入')
login.click()
很多人在用selenium定位頁面元素的時候會遇到定位不到的問題,明明元素就在那兒,就是定位不到,這種情況很有可能是frame 在搞鬼(可能原因之一),可以去仔細看看你網頁的DOM樹!
frame標籤有frameset、frame、iframe三種,frameset跟其他普通標籤沒有區別,不會影響到正常的定位,而frame與iframe對selenium定位而言是一樣的,selenium有一組方法對frame進行操作:
driver.switch_to.frame(reference) # 切到指定frame,可用id或name(str)、index(int)、元素(WebElement)定位
driver.switch_to.parent_frame() # 切到父级frame,如果已是主文档,则无效果
driver.switch_to.default_content() # 切到主文档,DOM树最开始的<html>标签
selenium提供了switch_to.frame()方法來切換frame
switch_to.frame(reference)
reference是傳入的參數,用來定位frame,可以傳入id、name、index以及selenium的WebElement對象,假設有如下HTML代碼 index.html:
<html lang="en">
<head>
<title>FrameTest</title>
</head>
<body>
<iframe src="a.html" id="frame1" name="myframe"></iframe>
</body>
</html>
想要定位其中的iframe並切進去,可以通過如下代碼:
from selenium import webdriver
driver = webdriver.Firefox()
driver.switch_to.frame(0) # 1.用frame的index来定位,第一个是0
# driver.switch_to.frame("frame1") # 2.用id来定位
# driver.switch_to.frame("myframe") # 3.用name来定位
# driver.switch_to.frame(driver.find_element_by_tag_name("iframe")) # 4.用WebElement对象来定位
通常採用id和name就能夠解決絕大多數問題。但有時候frame並無這兩項屬性,則可以用index和WebElement來定位:
舉個例子:
<iframe src="myframetest.html" />
用xpath定位,傳入 WebElement 物件:
driver.switch_to.frame(driver.find_element_by_xpath("//iframe[contains(@src,'myframe')]"))
切到frame中之後,我們便不能繼續操作主文檔的元素,這時如果想操作主文檔內容,則需切回主文檔。
driver.switch_to.default_content()
有時候我們會遇到嵌套的frame,如下:
<html>
<iframe id="frame1">
<iframe id="frame2" / >
</iframe>
</html>
driver.switch_to.frame("frame1") # 先切到frame1
driver.switch_to.frame("frame2") # 再切到frame2
driver.switch_to.parent_frame() # 如果目前已是主文檔,則無效果
有了parent_frame()這個相當於後退的方法,我們可以隨意切換不同的frame,隨意的跳來跳去了。
所以只要善用以下三個方法,遇到frame分分鐘搞定:
driver.switch_to.frame(reference)
driver.switch_to.parent_frame()
driver.switch_to.default_content()
通過driver.execute()執行js代碼,達到目的。
driver.execute_script('window.scrollBy(0,1000)')
scrollBy(x,y)中,x為必須參數,表示向右滾動的像素值;y也為必須參數,表示向下滾動的像素值
driver.execute_script('window.scrollTo(0,1000)')
scrollTo(x,y) 中,x為必要參數,表示要在窗口文檔顯示區左上角顯示的文檔的x坐標;y也為必要參數,表示要在窗口文檔顯示區左上角顯示的文檔的y坐標
參考:.body.scrollHeight doesn't work in Firefox
可以在 Chrome 的監控視窗的Console 下指令取得。
兩個指令皆可使用,但在某些網站(如:Youtube)這兩個指令,可能會有其中一個失效。
document.body.scrollHeight
document.documentElement.scrollHeight
selenium 捲軸拉到底:
方法一:
driver.execute_script('window.scrollTo(0,document.body.scrollHeight)')
方法二:
driver.execute_script('window.scrollTo(0,document.documentElement.scrollHeight)')